package com.foxmail.yusp75.myexam;
/*
Copyright 2017 Yu shanpeng

*/

import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.InputType;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;

import com.afollestad.materialdialogs.MaterialDialog;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import com.mikepenz.materialdrawer.Drawer;
import com.mikepenz.materialdrawer.DrawerBuilder;
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem;
import com.mikepenz.materialdrawer.model.SecondarySwitchDrawerItem;
import com.mikepenz.materialdrawer.model.SectionDrawerItem;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Locale;
import java.util.Objects;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import io.realm.Realm;
import io.realm.RealmQuery;
import io.realm.RealmResults;


public class MainActivity extends AppCompatActivity {

    private static final int REQUEST_PAPER = 10;
    private final String[] mode = {"单选", "多选", "判断"};

    private Realm mRealm;

    private TextView t_question;
    private TextView t_question_type;
    private TextView t_paper_c;
    private TextView t_questiong_num;
    private FloatingActionButton fab;
    private Fragment current_fragment;

    private ArrayList<Question> questions;

    private String your_anwser;
    private int mode_question = 0;
    private int position_fragment = -1;
    private Question question;

    private boolean anwser_is_show = false;
    private boolean by_order = false;
    private boolean only_wrong = false;
    private boolean only_bookmark = false;
    private int num_questions;
    private int num_done;  // 已做题目

    private int index = 0;
    private String paper_c = "信贷考试";

    private SingleSelectFragment fragment_0;
    private MultipleFragment fragment_1;
    private JudgeFragment fragment_2;

    private long back_pressed = 0;
    private Drawer mDrawer;
    private Toolbar toolbar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // database
        mRealm = Realm.getDefaultInstance();
        questions = new ArrayList<>();

        init_ui();

        if (savedInstanceState != null) {
            mode_question = savedInstanceState.getInt("mode_question");
            position_fragment = savedInstanceState.getInt("position_fragment");
            index = savedInstanceState.getInt("index");

            anwser_is_show = savedInstanceState.getBoolean("anwser_is_show");
            by_order = savedInstanceState.getBoolean("by_order");
            only_bookmark = savedInstanceState.getBoolean("only_bookmark");
            only_wrong = savedInstanceState.getBoolean("only_wrong");

            paper_c = savedInstanceState.getString("paper_c");
        }

        slide_menu();
        mDrawer.getActionBarDrawerToggle().setDrawerIndicatorEnabled(true);
    }

    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);

        outState.putInt("mode_question", mode_question);
        outState.putInt("position_fragment", position_fragment);
        outState.putInt("index", index);

        outState.putBoolean("anwser_is_show", anwser_is_show);
        outState.putBoolean("by_order", by_order);
        outState.putBoolean("only_bookmark", only_bookmark);
        outState.putBoolean("only_wrong", only_wrong);

        outState.putString("paper_c", paper_c);
    }

    @Override
    protected void onResume() {
        if (mRealm.where(Question.class).equalTo("paper.name", "信贷考试").count() == 0) {
            new ImportData(getApplicationContext()).execute(R.raw.paper);
        } else {
            // 显示题目
            get_question(index);
        }
        super.onResume();
    }

    @Override
    protected void onDestroy() {
        mRealm.close();
        super.onDestroy();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        Intent intent;
        switch (item.getItemId()) {
            case R.id.m_about:
                intent = new Intent(this, AboutActivity.class);
                intent.putExtra("title", "关于");
                intent.putExtra("url", "file:///android_res/raw/about.html");
                startActivity(intent);
                break;
            case R.id.m_setting:
                intent = new Intent(this, SettingActivity.class);
                startActivity(intent);
                break;
            case R.id.m_select_paper:
                select_paper();
                break;
            case R.id.m_paper_format:
                intent = new Intent(this, AboutActivity.class);
                intent.putExtra("title", "试卷题格式");
                intent.putExtra("url", "file:///android_res/raw/paper_f.html");
                startActivity(intent);
                break;
        }
        return true;
    }

    @Override
    public void onBackPressed() {
        if (mDrawer != null && mDrawer.isDrawerOpen()) {  // 先关掉滑动菜单
            mDrawer.closeDrawer();
        } else {
            if (back_pressed + 2000 > System.currentTimeMillis()) {
                super.onBackPressed();
            } else {
                Snackbar.make(t_question, "再按一次退出", Snackbar.LENGTH_SHORT).show();
            }

            back_pressed = System.currentTimeMillis();
        }
    }

    /* 自定义函数 */
    // 下一题
    public void btnNextClick(View view) {
        if (question == null) {
            next_question();
        } else {
            // 比较答案
            try {
                if (question.getAnswer().equals(your_anwser)) {

                    Snackbar snackbar = Snackbar.make(t_question, "正确。", Snackbar.LENGTH_SHORT);
                    snackbar.getView().setBackgroundColor(Color.BLUE);
                    snackbar.addCallback(new Snackbar.Callback() {
                        @Override
                        public void onDismissed(Snackbar transientBottomBar, int event) {
                            super.onDismissed(transientBottomBar, event);
                            // 下一道题目
                            next_question();
                            // 已做题数
                            num_done++;
                            question_num();
                        }
                    });
                    snackbar.show();

                } else {
                    Snackbar snackbar = Snackbar.make(t_question, "错误！应是："
                            + question.getAnswer(), Snackbar.LENGTH_INDEFINITE);
                    snackbar.getView().setBackgroundColor(Color.RED);
                    snackbar.show();
                    snackbar.setActionTextColor(Color.WHITE);
                    snackbar.setAction("确定", view1 -> {
                        // 下一道题目
                        next_question();
                    });
                    // 记入错题集
                    if (!only_wrong) {
                        //realm.executeTransaction(realm -> question.incC_wrong());
                        mRealm.executeTransactionAsync(realm -> question.incC_wrong(), error -> error.printStackTrace());
                    }
                }
            } catch (NullPointerException e) {
                Toast.makeText(getApplicationContext(), "未做选择", Toast.LENGTH_SHORT).show();
                next_question();
            }
        }  // 前有题目显示
    }

    // 跳过
    public void btnSkipClick(View view) {
        next_question();
    }

    // 提示答案
    public void btnPromptClick(View view) {
        if (question != null) {
            Toast.makeText(getApplicationContext(), "答案是：" + question.getAnswer(), Toast.LENGTH_SHORT).show();
        }
    }

    // 收藏
    public void btnBookmarkClick(View view) {
        AtomicBoolean value = new AtomicBoolean(false);
        if (question != null) {
            mRealm.executeTransactionAsync(realm -> {
                        value.set(question.setBookmark());
                    }, () -> {
                        if (value.get())
                            Toast.makeText(getApplicationContext(), "已收藏", Toast.LENGTH_SHORT).show();
                        else
                            Toast.makeText(getApplicationContext(), "收藏已取消", Toast.LENGTH_SHORT).show();
                        bookmark();
                    },

                    Throwable::printStackTrace);

        }
    }

    // 跳到指定序号
    public void btnJumpClick(View view) {
        int max_len = Integer.toString(num_questions).length();

        new MaterialDialog.Builder(this)
                .title("输入")
                .content(String.format(Locale.CHINA, "题号范围是0-%d", num_questions - 1))
                .inputType(InputType.TYPE_CLASS_NUMBER)
                .inputRange(1, max_len, Color.RED)
                .input(null, null, (dialog, input) -> {
                    try {
                        int i = Integer.parseInt(input.toString());
                        if (i >= num_questions)
                            Toast.makeText(getApplicationContext(), "选择超出范围", Toast.LENGTH_SHORT).show();
                        else
                            get_question(i);
                    } catch (NumberFormatException e) {
                        e.printStackTrace();
                    }
                })
                .show();
    }

    // 下一个问题
    private void next_question() {
        // 按顺序
        int idx = 0;
        if (questions.size() == 0) return;

        if (by_order) {
            question = questions.get(index);
            if (index < questions.size() - 2) {
                idx = index;
                index++;
            } else {
                Toast.makeText(getApplicationContext(), "已经没有题目了", Toast.LENGTH_SHORT).show();
            }
        } else {
            Random random = new Random(System.currentTimeMillis());
            idx = random.nextInt(questions.size());
        }
        // 取下一题目
        get_question(idx);
    }

    private void get_question(int idx) {
        if (questions.size() == 0)
            read_data();
        // 复位选择状态
        switch (mode_question) {
            case 0:
                fragment_0.reset();
                break;
            case 1:
                fragment_1.reset();
                break;
            case 2:
                fragment_2.reset();
                break;
        }

        try {
            question = questions.get(idx);
        } catch (IndexOutOfBoundsException e) {
            Toast.makeText(getApplicationContext(), "无此序号的题目", Toast.LENGTH_SHORT).show();
        }

        // 显示答案
        if (anwser_is_show) {
            t_question.setText(question.getContent());
        } else {
            String content = question.getContent();
            Pattern pattern;
            if (question.getType().equals("判断")) {
                pattern = Pattern.compile("\\(\\s*[√×]+\\s*\\)");
            } else {
                pattern = Pattern.compile("\\(\\s*[ABCD]+\\s*\\)");
            }
            Matcher matcher = pattern.matcher(content);
            if (matcher.find()) {
                content = matcher.replaceAll("（）");
                t_question.setText(content);
            } else {
                Log.d("我", "匹配失败，" + question.getContent());
                t_question.setText(question.getContent());
            }
        }
        // 显示收藏图标
        bookmark();
        t_question_type.setText(String.format(" 类型：[%s]", question.getType()));

        // 答题按键片段
        switch (mode_question) {
            case 0:
                if (mode_question != position_fragment) {
                    position_fragment = mode_question;
                    changeToFragment(fragment_0);
                }
                break;
            case 1:
                if (mode_question != position_fragment) {
                    position_fragment = mode_question;
                    changeToFragment(fragment_1);
                }
                break;
            case 2:
                if (mode_question != position_fragment) {
                    position_fragment = mode_question;
                    changeToFragment(fragment_2);
                }

        } // switch

    }

    private void t() {
        String s = "1.企业流动资金贷款是指我行向企业发放的用于借款人日常生产(A )的人民币贷款。\n" +
                "A.经营周转   B.股权投资  C.固定资产建设  D.消费\n" +
                "2.流动资金贷款原则上以（  ）担保为主，（  ）担保为辅，审慎办理信用贷款。(C)\n" +
                "A.保证  抵质押     B.抵押   质押 \n" +
                "C.抵质押  保证     D.质押    保证";
        Pattern p = Pattern.compile("^\\d{1,3}.[\\s\\S]+D.[\\s\\S]+//$", Pattern.MULTILINE);
        Matcher m = p.matcher(s);
    }

    private void slide_menu() {
        mDrawer = new DrawerBuilder()
                .withActivity(this)
                .withToolbar(toolbar)
                .withActionBarDrawerToggle(true)
                .addDrawerItems(
                        new SectionDrawerItem().withName("题型"),
                        new PrimaryDrawerItem()
                                .withName("单选")
                                .withIcon(R.drawable.ic_circle)
                                .withSelectedIcon(R.drawable.ic_circle_c)
                                .withSelectable(true)
                                .withIdentifier(0),
                        new PrimaryDrawerItem()
                                .withName("多选")
                                .withIcon(R.drawable.ic_multiple_marked)
                                .withSelectedIcon(R.drawable.ic_multiple_marked_c)
                                .withSelectable(true)
                                .withIdentifier(1),
                        new PrimaryDrawerItem()
                                .withName("判断")
                                .withIcon(R.drawable.ic_right)
                                .withSelectedIcon(R.drawable.ic_right_c)
                                .withSelectable(true)
                                .withIdentifier(2),
                        new SectionDrawerItem().withName("选项"),
                        new SecondarySwitchDrawerItem()
                                .withName("显示答案")
                                .withSelectable(false)
                                .withIdentifier(10)
                                .withIcon(R.drawable.ic_show_answer)
                                .withOnCheckedChangeListener((drawerItem, buttonView, isChecked) -> anwser_is_show = isChecked)
                                .withSwitchEnabled(true),
                        new SecondarySwitchDrawerItem()
                                .withName("顺序答题")
                                .withSelectable(false)
                                .withIdentifier(11)
                                .withIcon(R.drawable.ic_view_order)
                                .withSwitchEnabled(true)
                                .withOnCheckedChangeListener((drawerItem, buttonView, isChecked) -> {
                                    by_order = isChecked;
                                    reset_num();
                                }),
                        new SecondarySwitchDrawerItem()
                                .withName("做收藏题")
                                .withSelectable(false)
                                .withIdentifier(12)
                                .withIcon(R.drawable.ic_bookmark_b)
                                .withSwitchEnabled(true)
                                .withOnCheckedChangeListener((drawerItem, buttonView, isChecked) -> {
                                    only_bookmark = isChecked;
                                    invalid_data();
                                }),
                        new SecondarySwitchDrawerItem()
                                .withName("做错题")
                                .withSelectable(false)
                                .withIdentifier(13)
                                .withIcon(R.drawable.ic_wront_only)
                                .withSwitchEnabled(true)
                                .withOnCheckedChangeListener((drawerItem, buttonView, isChecked) -> {
                                    only_wrong = isChecked;
                                    invalid_data();
                                })
                )

                .withOnDrawerItemClickListener((view, position, drawerItem) -> {
                    if (drawerItem != null) {
                        switch ((int) drawerItem.getIdentifier()) {
                            case 0:  // 单选
                                mode_question = 0;
                                t_question_type.setText(String.format("类型：[%s]，", "单选"));
                                break;

                            case 1:  // 多选
                                mode_question = 1;
                                t_question_type.setText(String.format("类型：[%s]，", "多选"));
                                break;

                            case 2:  // 判断
                                mode_question = 2;
                                t_question_type.setText(String.format("类型：[%s]，", "判断"));
                                break;
                        }

                        invalid_data();

                    } //if
                    return false;
                })
                .build();
        //mDrawer.setSelection(0, true);
        // init
        mDrawer.setSelection(mode_question, false);
        ((SecondarySwitchDrawerItem) mDrawer.getDrawerItem(10)).withChecked(anwser_is_show);
        ((SecondarySwitchDrawerItem) mDrawer.getDrawerItem(11)).withChecked(by_order);
        ((SecondarySwitchDrawerItem) mDrawer.getDrawerItem(12)).withChecked(only_bookmark);
        ((SecondarySwitchDrawerItem) mDrawer.getDrawerItem(13)).withChecked(only_wrong);
    }

    private void read_data() {
        /*
        RealmResults<Paper> papers = realm.where(Paper.class).equalTo("name", paper_c).findAll();
        RealmList<Question> Questions = papers.get(0).getQuestions();
        RealmQuery<Question> query = Questions.where();
        */
        RealmQuery<Question> query = mRealm.where(Question.class).equalTo("paper.name", paper_c);
        // filter
        if (!only_wrong || !only_bookmark) {
            query.equalTo("type", mode[mode_question]);
        }
        if (only_bookmark) {
            query.equalTo("bookmark", true);
        }
        if (only_wrong) {
            query.greaterThan("c_wrong", 0);
        }
        RealmResults<Question> results = query.findAll();
        //add to array list
        questions.clear();
        if (results.size() > 0) {
            num_questions = results.size();
            question_num();
            for (int i = 0; i < results.size(); i++) {
                if (results.get(i).getContent().isEmpty()) {
                    Log.d("我", "空内容");
                    continue;
                }
                questions.add(results.get(i));
            }
        } else {
            //Toast.makeText(getApplicationContext(), "无符合条件的题目", Toast.LENGTH_SHORT).show();
            t_question.setText("无符合条件的题目");
        }
        //
        //realm.close();
    }

    public void init_ui() {
        // Handle Toolbar
        toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        toolbar.setTitle("我的考试");

        //ui
        t_paper_c = findViewById(R.id.paper_c);
        t_paper_c.setText(String.format("试卷：%s", paper_c));
        t_question = findViewById(R.id.question);
        t_questiong_num = findViewById(R.id.question_num);

        t_question_type = findViewById(R.id.question_type);
        t_question_type.setText(String.format("类型：[%s] ", "单选"));

        fab = findViewById(R.id.fab);
        fab.hide();

        fragment_0 = SingleSelectFragment.newInstance(null, null);
        fragment_0.setmListener(c -> your_anwser = c);
        fragment_1 = MultipleFragment.newInstance(null, null);
        fragment_1.setmListener(c -> your_anwser = c);
        fragment_2 = JudgeFragment.newInstance(null, null);
        fragment_2.setmListener(c -> your_anwser = c);

        current_fragment = null;

        //Show the hamburger icon
        Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(false);
    }

    // 异步导入数据
    private class ImportData extends AsyncTask<Integer, Integer, Question> {
        private ProgressBar pb;
        private final Context context;
        private final MaterialDialog diag;

        public ImportData(Context context) {
            this.context = context;
            diag = new MaterialDialog.Builder(MainActivity.this)
                    .title("导入数据")
                    .content("试卷：信贷考试")
                    .progress(true, 0)
                    .progressIndeterminateStyle(false)
                    .build();
        }

        @Override
        protected void onPreExecute() {
            diag.show();
            super.onPreExecute();
        }


        @Override
        protected Question doInBackground(Integer... values) {
            InputStream stream = context.getResources().openRawResource(values[0]);
            data("信贷考试", stream);
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            pb.setProgress(values[0]);
        }

        @Override
        protected void onPostExecute(Question question) {
            super.onPostExecute(question);
            // imported
            diag.dismiss();
            //invalid_data();
            get_question(index);
        }

    }

    // 收藏按钮
    private void bookmark() {
        if (question != null) {
            if (!fab.isShown()) {
                fab.show();
            }
            if (question.isBookmark()) {
                fab.setImageResource(R.drawable.ic_bookmark_c);
            } else {
                fab.setImageResource(R.drawable.ic_bookmark);
            }
        } else {
            fab.hide();
        }
    }

    public static void data(final String paper, InputStream stream) {
        String p_0 = "^\\d{1,3}.[\\s\\S]+";  // 问题
        String p_1 = "\\b[ABCD]+\\b\\s*";         // 答案
        String p_3 = "[√×]+\\s*";

        String type = "单选";
        String type_prior = "单选";
        Realm mRealm = Realm.getDefaultInstance();

        Pattern pattern;
        Matcher matcher;
        String line;
        String answer = "?";
        boolean type_first = true;
        String paper_c = paper;

        if (paper.isEmpty()) {
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy_MM_dd_HHmmss", Locale.CHINA);
            Date curDate = new Date(System.currentTimeMillis());
            String str = formatter.format(curDate);
            paper_c = "试题" + str;
        }

        // 不存在，新建库
        mRealm.beginTransaction();
        // 试卷库是否已经存在？
        Paper paper_obj;
        RealmResults<Paper> papers = mRealm.where(Paper.class).equalTo("name", paper).findAll();
        if (papers.size() > 0) {
            paper_obj = papers.get(0);
        } else {
            paper_obj = mRealm.createObject(Paper.class, UUID.randomUUID().toString());
            paper_obj.setName(paper_c);
        }
        /* start */
        try {
            InputStreamReader streamReader = new InputStreamReader(stream, "gbk");
            BufferedReader reader = new BufferedReader(streamReader);

            final StringBuilder buffer = new StringBuilder();
            try {
                while ((line = reader.readLine()) != null) {
                    line = line.trim();
                    if (line.isEmpty())
                        continue;
                    // 单选，多选，判断 u
                    pattern = Pattern.compile("单选|多选|判断");
                    matcher = pattern.matcher(line);
                    if (matcher.find()) {                     // 类型
                        type = matcher.group();
                        if (type_first) {
                            type_first = false;
                            type_prior = type;
                        }
                        //Log.d("我的类型", type);
                    } else {
                        pattern = Pattern.compile(p_0);
                        matcher = pattern.matcher(line);
                        // 1 问题
                        if (matcher.matches()) {                   // 问题
                            // 保存到database
                            if (!buffer.toString().isEmpty() && !answer.equals("?")) {
                                Question question = mRealm.createObject(Question.class,
                                        UUID.randomUUID().toString());
                                question.setAnswer(answer.trim());
                                question.setContent(buffer.toString());
                                question.setType(type_prior);
                                // 加到试卷
                                Objects.requireNonNull(paper_obj).getQuestions().add(question);

                                // clear prior
                                buffer.delete(0, buffer.length());
                                //publishProgress(count_question);
                            } else {
                                buffer.delete(0, buffer.length());
                            }

                            // 提取答案
                            if (type_prior.equals("判断")) {
                                pattern = Pattern.compile(p_3);    // 判断 √，×
                            } else {
                                pattern = Pattern.compile(p_1);
                            }
                            matcher = pattern.matcher(line);
                            if (matcher.find()) {                  // 答案
                                answer = matcher.group();
                                //line = matcher.replaceAll("");
                            } else {
                                answer = "?";
                            }
                        }
                        line = line + "\n";
                        buffer.append(line);
                        type_prior = type;
                    } // title
                    // while
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        /* end */
        mRealm.commitTransaction();

        // close
        mRealm.close();
    }

    private void question_num() {
        t_questiong_num.setText(String.format(Locale.CHINA, " 总数：%d，已做：%d", num_questions, num_done));
    }

    private void reset_num() {
        index = 0;
        num_done = 0;
        question_num();
    }

    private void invalid_data() {
        reset_num();
        question = null;
        read_data();
        next_question();
    }

    private void select_paper() {
        final ArrayList<String> list = new ArrayList<>();
        RealmResults<Paper> papers = mRealm.where(Paper.class).findAll();
        if (papers.size() > 0) {
            for (int i = 0; i < papers.size(); i++) {
                list.add(Objects.requireNonNull(papers.get(i)).getName());
            }
        } else {
            list.add("信贷考试");
        }
        new MaterialDialog.Builder(this)
                .title("选择一个试卷")
                .items(list)
                .itemsCallback((dialog, view, which, text) -> {
                    paper_c = list.get(which);
                    t_paper_c.setText(String.format("试卷：%s", paper_c));
                    // 刷新数据
                    invalid_data();
                })
                .show();
    }

    private void changeToFragment(Fragment to) {
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        if (current_fragment != null)
            transaction.hide(current_fragment);
        if (to.isAdded()) {
            transaction.show(to);
        } else {
            transaction.add(R.id.container, to);
        }
        transaction.commit();
        current_fragment = to;
    }


    // end
}
